package com.zn.util;

import com.alibaba.fastjson.JSONObject;
import com.zn.entity.OptionMarketTickDataField;
import com.zn.entity.OptionTradingGoods;
import com.zn.service.MdInfoService;
import com.zn.vo.EtfMdInfo;
import com.zn.vo.Response;
import com.zn.vo.SinaMarketDataField;
import com.zn.vo.SocketJsonData;
import com.zn.web.rpc.MdRemoteCall;
import com.zn.websocket.group.ChannelGroups;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


@Component
@Order(1)
public class AsyncTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncTask.class);
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private MdRemoteCall mdRemoteCall;
    @Autowired
    private MdInfoService mdInfoService;
    private ExecutorService pool = Executors.newCachedThreadPool();

    @Async("executorPool")
    public void getEtfMdInfo() throws Exception{
        Map<Object, Object> mapTarget = redisTemplate.opsForHash().entries(Constant.TARGET_CODE_LIST);
        for (Object key : mapTarget.keySet()) {
            String tradingGoods = redisTemplate.opsForValue().get(Constant.TRADE_DATE_INFO+key.toString());
            OptionTradingGoods optionTradingGoods = JSONObject.parseObject(tradingGoods, OptionTradingGoods.class);
            String rep = redisTemplate.opsForValue().get(Constant.DATE_OF_TRANSACTION);
            Response response = JSONObject.parseObject(rep, Response.class);
            boolean tradingFlag = mdInfoService.checkTradingTime(optionTradingGoods.getTradingTime(), response);
            if (!tradingFlag){
                break;
            }
            String etfMdInfoApiStr = mdRemoteCall.getEtfMdInfo(key.toString());
            String[] etfMdInfos = mdRemoteCall.subStringSinaData(etfMdInfoApiStr);
            if (etfMdInfos != null) {
                ////var hq_str_s_sh510050="50ETF,2.453,0.011,0.45,2836180,69702";
                EtfMdInfo etfMdInfo = new EtfMdInfo(etfMdInfos[0], etfMdInfos[1], etfMdInfos[3],etfMdInfos[2],  etfMdInfos[4], etfMdInfos[5]);
                Object jsonMd = JSONObject.toJSON(etfMdInfo);
                //主力合约列表
                SocketJsonData<EtfMdInfo> socketJsonData=new SocketJsonData<EtfMdInfo>(Constant.ETF,etfMdInfo);
                //深度行情json
                Object marketDataFieldToJson= JSONObject.toJSON(socketJsonData);
                //二进制推送 推送压缩后的包
                byte [] data= GZIPUtils.compress(marketDataFieldToJson.toString());
                ByteBuf byteBuf = Unpooled.buffer(data.length * 3);
                byteBuf.writeBytes(data);
                ChannelGroups.writeByEtf(new BinaryWebSocketFrame(byteBuf));
                String jieya=GZIPUtils.uncompressToString(data);
                LOGGER.info("getEtfMdInfo 解压后的数据包" + jieya);
                redisPut(Constant.TARGET_CODE_LIST, key.toString(), jsonMd.toString());
            }
        }
    }

    /**
     * 获取首页参考行情的方法
     * @throws Exception
     */
    @Async("executorPool")
    public void getReferMdInfo() throws Exception{
        Map<Object, Object> mapRefer = redisTemplate.opsForHash().entries(Constant.SINA_REFER_MD_INFO);
        for (Object key : mapRefer.keySet()) {
            Object referMdInfo=redisTemplate.opsForHash().get(Constant.SINA_REFER_MD_INFO, key);
            JSONObject referMdInfo2Json=JSONObject.parseObject(referMdInfo.toString());
            String rep = redisTemplate.opsForValue().get(Constant.DATE_OF_TRANSACTION);
            Response response = JSONObject.parseObject(rep, Response.class);
            boolean tradingFlag = mdInfoService.checkTradingTime(referMdInfo2Json.getString("tradingTime"), response);
            if (!tradingFlag){
                break;
            }
            String referMdInfoApiStr = mdRemoteCall.getReferMdInfo(key.toString());
            String[] etfMdInfos = mdRemoteCall.subStringSinaData(referMdInfoApiStr);
            if (etfMdInfos != null) {
                ////var hq_str_s_sh510050="50ETF,2.453,0.011,0.45,2836180,69702";
                EtfMdInfo etfMdInfo = new EtfMdInfo(etfMdInfos[0], etfMdInfos[1], etfMdInfos[3],etfMdInfos[2],  etfMdInfos[4], etfMdInfos[5]);
                Object jsonMd = JSONObject.toJSON(etfMdInfo);
                //主力合约列表
                SocketJsonData<EtfMdInfo> socketJsonData=new SocketJsonData<EtfMdInfo>(Constant.ETF,etfMdInfo);
                //深度行情json
                Object marketDataFieldToJson= JSONObject.toJSON(socketJsonData);
                //二进制推送 推送压缩后的包
                byte [] data= GZIPUtils.compress(marketDataFieldToJson.toString());
                ByteBuf byteBuf = Unpooled.buffer(data.length * 3);
                byteBuf.writeBytes(data);
                ChannelGroups.writeByEtf(new BinaryWebSocketFrame(byteBuf));
                String jieya=GZIPUtils.uncompressToString(data);
                LOGGER.info("getReferMdInfo 解压后的数据包" + jieya);
                redisPut(Constant.SINA_REFER_MD_LIST, key.toString(), jsonMd.toString());
            }
        }
    }

    /**
     * 获取补充的合约行情
     */
    @Async("executorPool")
    public void getSupplementTick()throws Exception{
        String nowDate=DateUtils.convertDateToString(new Date());
        String hashKey=Constant.INSTRUMENT_CODE_INFO+nowDate;
        Map<Object, Object> supplementTick = redisTemplate.opsForHash().entries(hashKey);
        for (Object key : supplementTick.keySet()) {
            Object supplementTickInfo=redisTemplate.opsForHash().get(hashKey, key);
            JSONObject supplementTickInfo2Json=JSONObject.parseObject(supplementTickInfo.toString());
            String rep = redisTemplate.opsForValue().get(Constant.DATE_OF_TRANSACTION);
            Response response = JSONObject.parseObject(rep, Response.class);
            boolean tradingFlag = mdInfoService.checkTradingTime(supplementTickInfo2Json.get("tradingTime").toString(), response);
            if (!tradingFlag){
                break;
            }
            String instrumentMonth=supplementTickInfo2Json.getString("instrumentMonth");
            SinaMarketDataField sinaMarketDataField = mdRemoteCall.getSinaMdInfo(key.toString());
            if(sinaMarketDataField==null){
                break;
            }
            OptionMarketTickDataField optionMarketTickDataField=new OptionMarketTickDataField(
                    key.toString(),sinaMarketDataField.getLastPrice(),sinaMarketDataField.getOpenInterest(),sinaMarketDataField.getPreClosePrice(),
                    sinaMarketDataField.getOpenPrice(),sinaMarketDataField.getUpperLimitPrice(),sinaMarketDataField.getLowerLimitPrice(),
                    sinaMarketDataField.getAskPrice5(),sinaMarketDataField.getAskVolume5(),sinaMarketDataField.getAskPrice4(),sinaMarketDataField.getAskVolume4(),
                    sinaMarketDataField.getAskPrice3(),sinaMarketDataField.getAskVolume3(),sinaMarketDataField.getAskPrice2(),sinaMarketDataField.getAskVolume2(),
                    sinaMarketDataField.getAskPrice1(),sinaMarketDataField.getAskVolume1(),sinaMarketDataField.getBidPrice1(),sinaMarketDataField.getBidVolume1(),
                    sinaMarketDataField.getBidPrice2(),sinaMarketDataField.getBidVolume2(),sinaMarketDataField.getBidPrice3(),sinaMarketDataField.getBidVolume3(),
                    sinaMarketDataField.getBidPrice4(),sinaMarketDataField.getBidVolume4(),sinaMarketDataField.getBidPrice5(),sinaMarketDataField.getBidVolume5(),
                    sinaMarketDataField.getUpdateTime(),sinaMarketDataField.getHighPrice(),sinaMarketDataField.getLowPrice(),sinaMarketDataField.getVolume(),
                    sinaMarketDataField.getTurnover()
            );
            //主力合约列表
            SocketJsonData<OptionMarketTickDataField> socketJsonData=new SocketJsonData<OptionMarketTickDataField>(Constant.TICK,optionMarketTickDataField);
            //深度行情json
            Object marketDataFieldToJson= JSONObject.toJSON(socketJsonData);
            //二进制推送 推送压缩后的包
            byte [] data= GZIPUtils.compress(marketDataFieldToJson.toString());
            ByteBuf byteBuf = Unpooled.buffer(data.length * 3);
            byteBuf.writeBytes(data);
            /**直接推到MD_ALL合约中**/
            ChannelGroups.writeByMonth(instrumentMonth, new BinaryWebSocketFrame(byteBuf));
            /**更新tick的历史数据**/
            /**推送完成之后更新首页主力合约列表的合约最新值**/
            String tickKey=Constant.OPTION_TICKL_INFO+sinaMarketDataField.getTargetCode()+":"+instrumentMonth+":"+nowDate;
            redisTemplate.opsForHash().put(tickKey,optionMarketTickDataField.getInstrumentCode(),optionMarketTickDataField.toString());
            redisTemplate.expire(tickKey, 10, TimeUnit.DAYS);
            System.err.println("推送了------>"+marketDataFieldToJson.toString());

        }
    }

    public void redisPut(String key,String id,String value){
        pool.execute(new Thread(() -> {
            redisTemplate.opsForHash().put(key, id, value);
        }));
    }
}
